package astoliarskyi.lab2;

import java.math.BigDecimal;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class SumSin {
	
	private final int threadNumber;
	
	public static void main(String[] args) {
		SumSin sinSum = new SumSin(5);
		int N = 1000;
		double sum = sinSum.calculateSinSum(N);
		System.out.print("Sum = sin(-N) + sin(-N+1) + …  + sin(N-1) + sin(N) = ");
		System.out.println(sum);
	}
	
	public SumSin(int threadNumber){
		this.threadNumber = threadNumber;
	}
	
	public double calculateSinSum(int N){
		int tasksPerThread = (2*N+1) / threadNumber;
		int nextN = -N;
		List<SinSumTask> tasks = new LinkedList<>();
		
		while (nextN <= N){
			int upToN = (nextN+tasksPerThread<=N) ? nextN+tasksPerThread : N;
			SinSumTask task = new SinSumTask(nextN, upToN);
			tasks.add(task);
			new Thread(task).start();
			nextN = upToN + 1;
		}
		
		BigDecimal result = BigDecimal.valueOf(0);
		while (!tasks.isEmpty()){
			Iterator<SinSumTask> iterator = tasks.iterator();
			while (iterator.hasNext()){
				SinSumTask task = iterator.next();
				if (task.isDone()){
					result = result.add(task.getResult());
					iterator.remove();
				}
			}
		}
		
		return result.doubleValue();
	}
	
	private class SinSumTask implements Runnable{
		
		private int fromN;
		private int toN;
		private volatile boolean done = false;
		private BigDecimal result = BigDecimal.valueOf(0);
		
		public SinSumTask(int fromN, int toN){
			this.fromN = fromN;
			this.toN = toN;
		}

		@Override
		public void run() {
			for (int i=fromN; i<=toN; i++){
				result = result.add(BigDecimal.valueOf(Math.sin(i)));
			}
			done = true;
		}
		
		public boolean isDone(){
			return done;
		}
		
		public BigDecimal getResult(){
			return result;
		}
	}

}
